﻿

using HBase;
using HBase.db;
using System;
using System.Collections.Generic;
namespace hCommand {
    /**
   *┌────────────────────────────────────────────────┐
   *│　描    述：TransferChain                                                    
   *│　作    者：sgj                                              
   *│　版    本：1.0                                              
   *│　创建时间：2020/10/10 9:12:53                        
   *└────────────────────────────────────────────────┘
   **/
    public class Node : RAM, CacheData {
        private object lockData = new object();
        public List<Estimate> timeAxis = new List<Estimate>();
        public Estimate currentTimeAxis = null;
        public NodeType type = NodeType.未知;

        public int x;
        public int y;
        public int agvAngle;
        private int R { get; }
        private List<int[]> rangeList = new List<int[]>();
        public bool isKeyStn = false;//是否是关键点
        private List<Edge> beforeEdge = new List<Edge>();//当前点的边
        private List<Edge> nextEdge = new List<Edge>();//当前点的边

    
       
        public List<int> crashArray = new List<int>();
        List<NodeAngle> tmpNodeAngle = new List<NodeAngle>();
        public int stop = 0;
        public long lastNodeId { get; set; }


       public  bool  addNodeAngle(int angle, long time, Node defore,int beforAngle) {
            foreach (NodeAngle na in tmpNodeAngle) {
                if (na.angle == angle) {
                    if (na.tmpBeforDistance > time) {
                        tmpNodeAngle.Remove(na);
                        break;
                    } else { 
                        return false;
                    }
                } 
            }
            NodeAngle na1 = new NodeAngle();
            na1.before = defore;
            na1.node = this;
            na1.tmpBeforDistance = time;
            na1.angle = angle;
            na1.beforAngle= beforAngle; 
            tmpNodeAngle.Add(na1);
            return true;
        }

        public NodeAngle getBastNodeAngle() {

            NodeAngle b = null;
            foreach (NodeAngle na in tmpNodeAngle) {
                if (b == null || b.tmpBeforDistance > na.tmpBeforDistance) {
                    b = na;
                }
            }
            return b;
        }
        public NodeAngle getTmpBefore(int angle) {

        

            foreach (NodeAngle na in  tmpNodeAngle) {
                if (na.angle== angle) {
                    return na;
                }
            }

            return null;
        }

        public Edge getEdge(Node des) {

            foreach (Edge e in nextEdge) {
                if (e.desNode == des) {
                    return e;
                }
            }
            return null;
        }

        public int getEdgeTime(Node des) {
            Edge edge = getEdge(des);
            if (edge != null) {
                return edge.R;
            }
            return 10000000;
        }
        public void statStop() {
            stop = 0;
            for (int i = 0; i < timeAxis.Count; i++) {
                Estimate e = timeAxis[i];
                stop += e.getStopTime();
            }
        }
        public void addEstimate(Estimate e) {
            lock (lockData) {
                timeAxis.Add(e);
            }
        }
        public bool free() {
            return currentTimeAxis == null;
        }

        public Estimate getCurrent() {
            return currentTimeAxis;
        }
        public void clearCurrent(long eOrder) {
            if (isCurrent(eOrder)) {
                currentTimeAxis = null;
            }
            lock (lockData) {
                foreach (Estimate e in timeAxis) {
                    if (e.id == eOrder) {
                        timeAxis.Remove(e);
                        return;
                    }
                }
            }
        }

        public bool isCurrent(long eOrder) {
            if (currentTimeAxis == null) {
                return false;
            }
            return eOrder == currentTimeAxis.getId();
        }
        public void taskArrived(long taskNo) {
            foreach (Estimate e in timeAxis) {
                if (e.taskNo == taskNo) {
                    arrived(e);

                }
            }
        }

        public Estimate getEstimate(int taskNo) {
            for (int i = 0; i < timeAxis.Count; i++) {
                Estimate e = timeAxis[i];
                if (e.taskNo == taskNo) {
                    return e;
                }
            }
            return null;
        }

        public void arrived(Estimate me) {//下位机通知上位机当前位置
            if (me == null) {
                return;
            }
            if (currentTimeAxis != null) {//原来的还在
                return;
            }
            lock (me) {
                me.setBegin(DateTime.Now);
                currentTimeAxis = me;
                me.removeBefore();
            }
        }



        public DateTime getFreeTime(DateTime begin, Estimate me) {
            while (true) {
                bool isIn = false;
                for (int i = 0; i < timeAxis.Count; i++) {
                    Estimate e = timeAxis[i];
                    if (me != null && e.getId() == me.getId()) {
                        continue;
                    }
                    if (e.isIn(begin)) {
                        begin = e.endDate;
                        isIn = true;
                        break;
                    }
                }
                if (!isIn) {
                    break;
                }
            }
            return begin;

        }




        public Estimate getTaskEstimate(int taskNo) {
            Estimate res = null;
            for (int i = 0; i < timeAxis.Count; i++) {
                Estimate e = timeAxis[i];
                if (e.taskNo == taskNo) {
                    if (res != null) {
                        throw new Exception(taskNo + "有多个任务在节点" + getId() + res.getId() + "&" + e.getId());
                    }
                    res = e;
                }
            }
            return res;
        }


        public int getR() {
            return R;
        }



        public List<Edge> getNextEdge() {
            return nextEdge;
        }

        public List<Edge> getBeforeEdge() {
            return beforeEdge;
        }
        public void addBeforeEdge(Edge id) {
            beforeEdge.Add(id);
        }
        public long getPredictTime() {
            return R * 10000;
        }



       
        public bool isArived() {
            return tmpNodeAngle.Count > 0;
        }

        public long getTmpBeforDistance(int angle) {

            foreach (NodeAngle na in tmpNodeAngle) {
                if (na.angle == angle) {
                    return na.tmpBeforDistance;
                }
            }
            return long.MaxValue/3;
        }

        public long getArivedTime() {
            long tmpBeforDistance = long.MaxValue / 3;

            foreach (NodeAngle na in tmpNodeAngle) {
                if (na.angle <tmpBeforDistance) {
                    tmpBeforDistance= na.tmpBeforDistance;
                }
            }
            return tmpBeforDistance;
        }
        public void setTmpBeforDistance(long time,int angle) {


            NodeAngle na1 = new NodeAngle();
          
            na1.node = this;
            na1.tmpBeforDistance = time;
            na1.angle = angle;

            tmpNodeAngle.Add(na1);
 

        }
        public void clearTmp() {
            tmpNodeAngle.Clear();

        }




        public Node(BStn stn) : this(stn, stn.id) {

        }
        public Node(BStn stn, long eId) {
            lastNodeId = eId;
            id = eId;
            R = stn.distance;
            x = stn.x;
            y = stn.y;
            agvAngle = stn.agvAngle;
            isKeyStn = isKeyStn || stn.isKeyPoint > 0;
            string[] range = stn.area.Split(';');
            foreach (string r in range) {
                string[] arr = r.Split(',');
                if (arr.Length == 1) {
                    rangeList.Add(new int[] { int.Parse(arr[0]), int.Parse(arr[0]) });
                } else {
                    rangeList.Add(new int[] { int.Parse(arr[0]), int.Parse(arr[1]) });
                }
            }
            if (!String.IsNullOrEmpty(stn.crash)) {
                String[] arr = stn.crash.Split(',');
                foreach (String a in arr) {
                    crashArray.Add(int.Parse(a));
                }
            }

        }

        public bool isConfig(int p) {
            if (this.id == p) {
                return true;
            }
            foreach (var range in this.rangeList) {
                if (range[0] <= p && range[1] >= p) {
                    return true;
                }
            }
            return false;
        }
        private static String name = typeof(Node).Name;
        public static Node getNode(int id) {
            return MyCache.getValue<Node>(name, id);
        }

        public static Node getConfig(int p, bool setNewEid = false) {
            Node res = Node.getNode(p);
            if (res == null) {
                res = MyCache.queryUnique<Node>((a) => {
                    return ((Node)a).isConfig(p);
                }, "节点过多" + p);
            }

            if (setNewEid) {
                res.lastNodeId = p;
            }
            return res;
        }

    }

    public enum NodeType {
        未知 = 0,
        双向管道 = 1,
        单向管道 = 2,
        死胡同 = 3,
        岔路口 = 4,
    }
}
